<?php

namespace App\Http\Validate;

use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Str;
use Illuminate\Validation\ValidationException;
use Kuafu\File\FileUtil;

/**
 * @author GreenLeaf <786407418@qq.com>
 *
 * @datetime 2022-02-24 13:55:42
 */
abstract class BaseValidate
{

    /**
     * 注册校验规则
     *
     * @return mixed
     */
    abstract static function registerValidateRules(): void;


    /**
     * 校验字段对应错误信息
     *
     * @var array
     */
    public static array $validateMsg = [];

    /**
     * 校验字段映射
     *
     * @var array
     */
    public static array $attributes = [];

    /**
     * 获取校验错误信息
     *
     * @return array|string[]
     */
    public static function getValidateMsg($extra = []): array
    {
        return array_merge(static::$validateMsg, $extra);
    }


    /**
     * 校验参数预处理
     *
     * @param array $data
     * @return array
     */
    public static function beforeValidate(array $data): array
    {
        return $data;
    }

    /**
     * 获取规则信息
     *
     * @param array $fields
     * @return string[]
     */
    abstract static function getRules(array $fields = []): array;

    /**
     * 获取校验参数规则
     *
     * @param array $rules
     * @param array $fields
     * @return array|mixed
     */
    public final static function getActuallyRules(array $rules = [], array $fields = []): array
    {
        return empty($fields) ? $rules : (new Collection($rules))->filter(function ($v, $k) use ($fields) {
            if (in_array($k, $fields)) {
                return true;
            }
            return false;
        })->toArray();
    }

    /**
     * 获取校验参数列表
     *
     * @param array $requestParams
     * @param array $ruleKeys
     * @param \Closure|null $closure
     * @return array
     */
    public final static function getRequestParams(
        array $requestParams,
        array $ruleKeys,
        \Closure $closure = null
    ): array {
        $realParams = [];
        //获取验证参数 & 公有处理参数
        foreach ($requestParams as $field => $value) {
            if (in_array($field, $ruleKeys)) {
                if (Str::endsWith(strtoupper($field), 'IMG')) {
                    $realParams[$field] = str_replace(FileUtil::domain(), '', $value);
                } else {
                    $realParams[$field] = $value;
                }
            }
        }

        //特殊参数闭包特殊处理
        if ($closure instanceof \Closure) {
            return $closure($realParams);
        }

        return $realParams;
    }


    /**
     * 基础校验 & 参数获取
     *
     * @param $params
     * @param $validateFields
     * @param \Closure|null $resolveParams
     * @param array|null $extraRules
     * @param array|null $validateMsg
     * @return array
     * @throws ValidationException
     */
    public final static function baseValidate(
        $params,
        $validateFields,
        \Closure $resolveParams = null,
        array $extraRules = null,
        array $validateMsg = null
    ): array {
        static::registerValidateRules();

        //获取验证规则｜覆盖原有验证规则
        $validateRules = static::getRules($validateFields);
        $validateRules = ($extraRules ? array_merge($validateRules, $extraRules) : $validateRules);

        //预处理参数
        $params = static::beforeValidate($params);

        //校验数据
        self::validateCheck($params, $validateRules, $validateMsg ?? [], static::$attributes);
        return self::getRequestParams($params, array_keys($validateRules), $resolveParams);//获取请求校验数据并处理
    }


    /**
     * @param array $data
     * @param array $rule
     * @param array $message
     * @param array $attributes
     * @throws ValidationException
     */
    protected final static function validateCheck(
        array $data = [],
        array $rule = [],
        array $message = [],
        array $attributes = []
    ) {
        $validator = Validator::make($data, $rule, $message, $attributes);

        if ($validator->fails()) {
            throw new ValidationException($validator);
        }
    }
}
